const Parse = require('parse/node');

// Initialize Parse
Parse.initialize("NwrNwnQTDLxBoneM8ziHiyJCQ56miSCLEWYpPk4i", "KT0OObN8SpUJ4AklXs4QJwcoYsJPhkvMxvKSAXQe");
Parse.serverURL = 'https://parseapi.back4app.com/';

// Cloud Job: matchPoolCron - Process match pool every 1 second
Parse.Cloud.job("matchPoolCron", async (request) => {
  const { params, master, user } = request;
  const startTime = new Date();
  let roomsCreated = 0;
  let playersMatched = 0;
  
  try {
    console.log("Starting match pool processing at:", startTime);
    
    // Get all players in match pool grouped by difficulty
    const matchPoolQuery = new Parse.Query("MatchPool");
    const matchPoolEntries = await matchPoolQuery.find({ useMasterKey: true });
    
    if (matchPoolEntries.length === 0) {
      console.log("No players in match pool");
      return {
        success: true,
        message: "No players to match",
        playersProcessed: 0,
        roomsCreated: 0,
        executionTime: new Date() - startTime
      };
    }

    // Group by difficulty
    const playersByDifficulty = {};
    
    for (const entry of matchPoolEntries) {
      const difficulty = entry.get("difficulty") || 1;
      const userId = entry.get("userId");
      
      if (!playersByDifficulty[difficulty]) {
        playersByDifficulty[difficulty] = [];
      }
      
      // Check if user is not already in a room
      const userRoomQuery = new Parse.Query("Room");
      userRoomQuery.equalTo("users", entry.get("user"));
      const existingRoom = await userRoomQuery.first({ useMasterKey: true });
      
      if (!existingRoom) {
        playersByDifficulty[difficulty].push({
          entry: entry,
          user: entry.get("user"),
          username: entry.get("username"),
          userId: userId,
          difficulty: difficulty
        });
      }
    }

    // Process each difficulty level
    for (const difficulty in playersByDifficulty) {
      const players = playersByDifficulty[difficulty];
      
      console.log(`Processing ${players.length} players for difficulty ${difficulty}`);
      
      // Group players into rooms of max 6 (minimum 2 to start)
      while (players.length >= 2) {
        const roomPlayers = players.splice(0, Math.min(6, players.length));
        
        if (roomPlayers.length >= 2) {
          const room = await createRoomFromMatchPool(roomPlayers, parseInt(difficulty));
          if (room) {
            roomsCreated++;
            playersMatched += roomPlayers.length;
            console.log(`Created room ${room.id} with ${roomPlayers.length} players`);
          }
        }
      }
    }

    const executionTime = new Date() - startTime;
    
    console.log(`Match pool processing completed in ${executionTime}ms`);
    console.log(`Rooms created: ${roomsCreated}, Players matched: ${playersMatched}`);
    
    return {
      success: true,
      message: "Match pool processed successfully",
      playersProcessed: playersMatched,
      roomsCreated: roomsCreated,
      executionTime: executionTime,
      timestamp: new Date()
    };

  } catch (error) {
    console.error("Error in matchPoolCron job:", error);
    
    return {
      success: false,
      error: error.message,
      playersProcessed: 0,
      roomsCreated: 0,
      executionTime: new Date() - startTime,
      timestamp: new Date()
    };
  }
});

// Helper function to create room from match pool
async function createRoomFromMatchPool(players, difficulty) {
  try {
    const Room = Parse.Object.extend("Room");
    const room = new Room();
    
    room.set("difficulty", difficulty);
    room.set("status", "playing");
    room.set("unansweredCount", 0);
    room.set("maxPlayers", 6);
    
    // Add players to room
    const users = players.map(p => p.user);
    room.set("users", users);
    
    await room.save(null, { useMasterKey: true });

    // Remove players from match pool
    const playerEntries = players.map(p => p.entry);
    await Parse.Object.destroyAll(playerEntries, { useMasterKey: true });

    // Send push notifications to all players
    const pushQuery = new Parse.Query(Parse.Installation);
    pushQuery.containedIn("user", users);
    
    const usernames = players.map(p => p.username).join(", ");
    
    await Parse.Push.send({
      where: pushQuery,
      data: {
        alert: `🎮 游戏开始！${difficulty}星难度房间，玩家: ${usernames}`,
        sound: "default",
        roomId: room.id,
        type: "game_started",
        difficulty: difficulty,
        playerCount: players.length
      }
    }, { useMasterKey: true });

    // Post system chat message
    const AudienceChat = Parse.Object.extend("AudienceChat");
    const systemChat = new AudienceChat();
    systemChat.set("roomId", room.id);
    systemChat.set("username", "系统");
    systemChat.set("text", `🎉 房间创建成功！${difficulty}星难度，${players.length}位玩家加入游戏`);
    systemChat.set("ts", Date.now());
    await systemChat.save(null, { useMasterKey: true });

    console.log(`Room ${room.id} created successfully`);
    return room;
    
  } catch (error) {
    console.error("Error creating room from match pool:", error);
    throw error;
  }
}

// Additional helper functions for match pool management

// Clean up old match pool entries (older than 5 minutes)
Parse.Cloud.job("cleanupMatchPool", async (request) => {
  const startTime = new Date();
  
  try {
    const fiveMinutesAgo = new Date(startTime.getTime() - 5 * 60 * 1000);
    
    const oldEntriesQuery = new Parse.Query("MatchPool");
    oldEntriesQuery.lessThan("joinedAt", fiveMinutesAgo);
    const oldEntries = await oldEntriesQuery.find({ useMasterKey: true });
    
    if (oldEntries.length > 0) {
      await Parse.Object.destroyAll(oldEntries, { useMasterKey: true });
      console.log(`Cleaned up ${oldEntries.length} old match pool entries`);
    }
    
    return {
      success: true,
      message: `Cleaned up ${oldEntries.length} old entries`,
      entriesRemoved: oldEntries.length,
      executionTime: new Date() - startTime
    };
    
  } catch (error) {
    console.error("Error in cleanupMatchPool job:", error);
    return {
      success: false,
      error: error.message,
      entriesRemoved: 0,
      executionTime: new Date() - startTime
    };
  }
});

// Get match pool statistics
Parse.Cloud.define("getMatchPoolStats", async (request) => {
  try {
    const matchPoolQuery = new Parse.Query("MatchPool");
    const totalPlayers = await matchPoolQuery.count({ useMasterKey: true });
    
    const pipeline = [
      {
        group: {
          objectId: "$difficulty",
          difficulty: { $max: "$difficulty" },
          count: { $sum: 1 }
        }
      }
    ];
    
    const difficultyStats = await matchPoolQuery.aggregate(pipeline, { useMasterKey: true });
    
    return {
      success: true,
      totalPlayers: totalPlayers,
      byDifficulty: difficultyStats,
      timestamp: new Date()
    };
    
  } catch (error) {
    console.error("Error getting match pool stats:", error);
    return {
      success: false,
      error: error.message
    };
  }
});

// Manual trigger for testing
Parse.Cloud.define("testMatchPoolProcessing", async (request) => {
  try {
    // Run the match pool processing logic once
    const result = await processMatchPoolManual();
    return result;
    
  } catch (error) {
    console.error("Error in testMatchPoolProcessing:", error);
    return {
      success: false,
      error: error.message
    };
  }
});

// Manual processing function (same as job logic)
async function processMatchPoolManual() {
  const startTime = new Date();
  let roomsCreated = 0;
  let playersMatched = 0;
  
  try {
    // Get all players in match pool grouped by difficulty
    const matchPoolQuery = new Parse.Query("MatchPool");
    const matchPoolEntries = await matchPoolQuery.find({ useMasterKey: true });
    
    if (matchPoolEntries.length === 0) {
      return {
        success: true,
        message: "No players to match",
        playersProcessed: 0,
        roomsCreated: 0,
        executionTime: new Date() - startTime
      };
    }

    // Group by difficulty
    const playersByDifficulty = {};
    
    for (const entry of matchPoolEntries) {
      const difficulty = entry.get("difficulty") || 1;
      const userId = entry.get("userId");
      
      if (!playersByDifficulty[difficulty]) {
        playersByDifficulty[difficulty] = [];
      }
      
      // Check if user is not already in a room
      const userRoomQuery = new Parse.Query("Room");
      userRoomQuery.equalTo("users", entry.get("user"));
      const existingRoom = await userRoomQuery.first({ useMasterKey: true });
      
      if (!existingRoom) {
        playersByDifficulty[difficulty].push({
          entry: entry,
          user: entry.get("user"),
          username: entry.get("username"),
          userId: userId,
          difficulty: difficulty
        });
      }
    }

    // Process each difficulty level
    for (const difficulty in playersByDifficulty) {
      const players = playersByDifficulty[difficulty];
      
      // Group players into rooms of max 6 (minimum 2 to start)
      while (players.length >= 2) {
        const roomPlayers = players.splice(0, Math.min(6, players.length));
        
        if (roomPlayers.length >= 2) {
          const room = await createRoomFromMatchPool(roomPlayers, parseInt(difficulty));
          if (room) {
            roomsCreated++;
            playersMatched += roomPlayers.length;
          }
        }
      }
    }

    const executionTime = new Date() - startTime;
    
    return {
      success: true,
      message: "Match pool processed successfully",
      playersProcessed: playersMatched,
      roomsCreated: roomsCreated,
      executionTime: executionTime,
      timestamp: new Date()
    };

  } catch (error) {
    console.error("Error in processMatchPoolManual:", error);
    
    return {
      success: false,
      error: error.message,
      playersProcessed: 0,
      roomsCreated: 0,
      executionTime: new Date() - startTime
    };
  }
}